import AlgUtil from "../libs/utils/AlgUtil";
import ResourceManageSingleton from "../libs/utils/ResourceManageSingleton";
import CharacterDTO from "../pojo/dto/CharacterDTO";
import CharacterPO from "../pojo/po/CharacterPO";
import CharacterEntity from "./CharacterEntity";

/*****************************
 *@file: CharacterManageSingleton
 *@author: 陈吕唐
 *@desc:
 *@date: 2024-02-27	18:23
 *****************************/
export default class CharacterManageSingle {
    /****************************************************************************************************************
     *Readonly 常量
     ****************************************************************************************************************/
    private static _single: CharacterManageSingle = undefined!;


    /**
     * 英雄表配置数据
     */
    private poMap: Map<number, CharacterPO> = new Map<number, CharacterPO>();


    /**
     * 英雄实体类配置数据
     */
    private entityMap: Map<number, CharacterEntity> = new Map<number, CharacterEntity>();

    /**
     * 当前出战角色ID集合
     */
    public teamSet: Set<number> = new Set();
    /****************************************************************************************************************
     *Property 定义变量
     ****************************************************************************************************************/
    /****************************************************************************************************************
     * Lifecycle 生命周期相关方法
     ****************************************************************************************************************/
    private constructor() {

    }
    /****************************************************************************************************************
     * Public 公有方法
     ****************************************************************************************************************/

    /**
     * 抽取英雄
     * @returns 
     */
    public prizeCharacter(): Promise<CharacterEntity> {
        let promise: Promise<CharacterEntity> = new Promise((resolve, reject) => {
            let dto = this.createPrize();
            let value = this.updateCharacterEntity(dto);
            resolve(value);
        });
        return promise;
    }

    /**
     * 角色升级
     * @param id 角色ID
     * @returns 
     */
    public upgradeCharacter(id: number): Promise<CharacterEntity> {
        let promise: Promise<CharacterEntity> = new Promise((resolve, reject) => {
            let dto: CharacterDTO = this.getEntityById(id);
            if (dto.lv >= 3) {
                reject(`等级满了`);
                return;
            }
            dto.lv++;
            let value = this.updateCharacterEntity(dto);
            resolve(value);
        });
        return promise;
    }

    /**
     * 出战角色
     * @param id 角色ID
     * @returns 
     */
    public playCharacter(id: number): Promise<void> {
        let promise: Promise<void> = new Promise((resolve, reject) => {
            let character = this.getEntityById(id);
            if (!character) {
                reject(`角色不存在`);
                return;
            }

            if (this.teamSet.size >= 3) {
                reject(`队伍已满`);
                return;
            }

            this.teamSet.add(id);
            resolve();
        });
        return promise;
    }

    /**
     * 角色下场
     * @param id 角色ID
     * @returns 
     */
    public releaseCharacter(id: number): Promise<void> {
        let promise: Promise<void> = new Promise((resolve, reject) => {
            this.teamSet.delete(id);
            resolve();
        });
        return promise;
    }
    /*************************************************
     * 
     ************************************************/
    public init() {
        this.initPO();
    }

    /**
     * 更新英雄数据
     * @param list 
     */
    public updateCharacterEntityList(list: CharacterDTO[]) {
        for (let i = 0; i < list.length; i++) {
            const element = list[i];
            this.updateCharacterEntity(element);
        }
    }


    /**
     * 根据id获取英雄实体类
     * @param id 
     * @returns 
     */
    public getEntityById(id: number): CharacterEntity {
        return this.entityMap.get(id);
    }
    /****************************************************************************************************************
     * private 私有方法
     ****************************************************************************************************************/
    /**
     * 初始化配置表数据
     */
    private initPO() {
        this.poMap.clear();
        let array: CharacterPO[] = ResourceManageSingleton.singleton.getJson(`Character`);
        for (let i = 0; i < array.length; i++) {
            const element = array[i];
            this.poMap.set(element.id, element);
        }

    }

    /**
     * 更新英雄数据
     * @param dto 
     */
    private updateCharacterEntity(dto: CharacterDTO) {
        let entity = this.entityMap.get(dto.id);
        if (!entity) {
            entity = this.createCharacterEntity(dto);
            this.entityMap.set(dto.id, entity);
        }
        entity.updateDTO(dto);
        return entity;
    }

    /**
     * 创建英雄实体类
     * @param dto 
     */
    private createCharacterEntity(dto: CharacterDTO): CharacterEntity {
        let po = this.poMap.get(dto.id);
        if (!po) {
            console.error(`CharacterManageSingle.createCharacterEntity:${dto.id} is not exist`);
            return null;
        }
        let vo = { ...po, ...dto };
        let entity = new CharacterEntity(vo);
        return entity;
    }
    /*******************************************
     * Test
     ******************************************/
    private createPrize(): CharacterDTO {

        let ids: number[] = [10041, 10051, 10001];

        let id = AlgUtil.pickRandomUniqueItems(ids, 1)[0];

        /**
         * 抽取数据
         */
        let dto: CharacterDTO = { id: id, lv: 1 };
        return dto;
    }
    /****************************************************************************************************************
     * Property Get && Set 属性的 get && set 函数
     ****************************************************************************************************************/
    public static get single() {
        if (!CharacterManageSingle._single) {
            CharacterManageSingle._single = new CharacterManageSingle();
        }
        return CharacterManageSingle._single;
    }

    /**
     * 当前用户拥有的角色
     */
    public get characterEntities(): CharacterEntity[] {
        return Array.from(this.entityMap.values());
    }
}